iT邦幫忙

2024 iThome 鐵人賽

DAY 6
0
JavaScript

React30——用 React 探索 JavaScript30 的魅力系列 第 10

[Day10]_Hold-Shift-and-Check-Checkboxes

  • 分享至 

  • xImage
  •  

Day10 是要實作可以用 Shift 來多選框框的題目

建立資料

const checkboxData: string[] = [
  "This is an inbox layout.",
  "Check one item",
  "Hold down your Shift key",
  "Check a lower item",
  "Everything in between should also be set to checked",
  "Try to do it without any libraries",
  "Just regular JavaScript",
  "Good Luck!",
  "Don't forget to tweet your result!",
];
  const [checkedItems, setCheckedItems] = useState<boolean[]>(
    new Array(checkboxData.length).fill(false)
  );
  const lastCheckedRef = useRef<number | null>(null);

多選功能

  • 判斷是否按到 Shift 且之前有選中框框

  • 將最後選中的和目前選到的中間所有項目,設定為相同的狀態

  const handleCheck = (
    event: ChangeEvent<HTMLInputElement>,
    index: number
  ): void => {
    const newCheckedItems = [...checkedItems];
    newCheckedItems[index] = !newCheckedItems[index];

    if (
      event.nativeEvent instanceof MouseEvent &&
      event.nativeEvent.getModifierState("Shift") &&
      lastCheckedRef.current !== null
    ) {
      const start = Math.min(index, lastCheckedRef.current);
      const end = Math.max(index, lastCheckedRef.current);
      for (let i = start; i <= end; i++) {
        newCheckedItems[i] = newCheckedItems[index];
      }
    }

    setCheckedItems(newCheckedItems);
    lastCheckedRef.current = index;
  };

畫面結構

    <div className="min-h-screen bg-gradient-to-br from-yellow-300 via-yellow-400 to-orange-400 flex items-center justify-center">
      <div className="max-w-md w-full bg-white rounded-lg shadow-xl overflow-hidden">
        {checkboxData.map((item, index) => (
          <div
            key={index}
            className="flex border-b border-gray-200 last:border-b-0"
          >
            <label className="px-5 flex flex-1 items-center cursor-pointer">
              <input
                type="checkbox"
                checked={checkedItems[index]}
                onChange={(event) => handleCheck(event, index)}
                className="h-5 w-5 mr-5 text-yellow-400 rounded focus:ring-yellow-400 focus:ring-opacity-25 cursor-pointer"
              />
              <span
                className={`flex-1 py-5 px-5 text-xl font-light border-l border-blue-100 transition-colors duration-200 ${
                  checkedItems[index] ? "bg-gray-100 line-through" : ""
                }`}
              >
                {item}
              </span>
            </label>
          </div>
        ))}
      </div>
    </div>

DEMO

https://codesandbox.io/p/devbox/ygkv63


上一篇
[Day09]_Dev-Tools-Domination
下一篇
[Day11]_Custom-Video-Player
系列文
React30——用 React 探索 JavaScript30 的魅力30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言